package ru.housewife.controllers;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import ru.common.Jsons;
import ru.common.hibernate.HibernateActionExecutor;
import ru.housewife.AppConstants;
import ru.housewife.cache.CacheManager;
import ru.housewife.form.*;
import ru.housewife.service.wares.SetPreferableWareForRecipesComponent;

import javax.servlet.http.HttpServletRequest;
import java.io.PrintWriter;
import java.util.*;

/**
 * Controller to work with wares
 *
 * @author Alexander Troshanin
 */
@Controller
public class WaresController extends AuthorizedController implements AppConstants {

    private final HibernateActionExecutor hiber;

    public WaresController(@Qualifier("houseWifesHibernate") HibernateActionExecutor hiber) {
        this.hiber = hiber;
    }

    @RequestMapping(value = "/get-select-wares-form.html")
    public ModelAndView getSelectWareForm() {
        List<WaresGroupForm> waresGroups = CacheManager.getInstance().getFirstLevelWaresGroups();
        return new ModelAndView("housewifes/wares/selectWareDialog-json-reply", "waresGroups", waresGroups);
    }

    @RequestMapping(value = "/get-wares-list.html")
    public ModelAndView getGetWares(@RequestParam(required = false) Long groupId,
                                    @RequestParam(required = false) Long ingredientId,
                                    @RequestParam(required = false) int page,
                                    HttpServletRequest request) {
        UserForm user = getUserForm(request);
        List<WareForm> waresFullList = null;
        if (groupId != null) {
            WaresGroupForm group = CacheManager.getInstance().getWaresGroupForm(groupId);
            if (group != null) {
                waresFullList = group.getWares();
            }
        } else if (ingredientId != null) {
            IngredientForm ingredient = CacheManager.getInstance().getIngredientForm(ingredientId);
            if (ingredient != null) {
                waresFullList = ingredient.getWares();
            }
        }

        List<WareForm> waresSubList;
        int pageCount;
        if (waresFullList != null) {
            int origSize = waresFullList.size();
            if (origSize > 0) {
                int from = SELECT_WARES_VIEW_PAGE_SIZE * page;
                from = (from >= origSize) ? 0 : from;
                int to = from + SELECT_WARES_VIEW_PAGE_SIZE;
                to = (to >= origSize) ? origSize : to;

                waresSubList = waresFullList.subList(from, to);
            } else {
                waresSubList = Collections.emptyList();
            }
            pageCount = getPageCount(SELECT_WARES_VIEW_PAGE_SIZE, origSize);
        } else {
            waresSubList = Collections.emptyList();
            pageCount = 0;
            page = 0;
        }

        List<WareFormView> waresViews = new ArrayList<WareFormView>(waresSubList.size());
        Map<Long, WareFormView> waresViewsToFillPrices = new HashMap<Long, WareFormView>(waresSubList.size());
        for (WareForm ware : waresSubList) {
            WareFormView wareView = new WareFormView(ware);
            waresViews.add(wareView);
            UserForm.UsersWare usersWare = user.getUsersWare(ware.getId());
            if (usersWare != null) {
                wareView.setRegionPrice(usersWare.getWareRegionPrice());
                wareView.setUserPrice(usersWare.getWareUserPrice());
            } else {
                waresViewsToFillPrices.put(ware.getId(), wareView);
            }
        }
        if (waresViewsToFillPrices.size() > 0) {
            CacheManager.getInstance().fillWaresViewsWithRegionPrices(user.getRegion(), waresViewsToFillPrices);
        }

        ModelAndView mv = new ModelAndView("housewifes/wares/waresList-json-reply");
        mv.addObject("wares", waresSubList);
        mv.addObject("waresViews", waresViews);
        mv.addObject("selectedPage", page);
        mv.addObject("pageCount", pageCount);
        mv.addObject("pageNums", generatePageNumsInfo(page, pageCount));
        return mv;
    }

    @RequestMapping(value = "/set-preferable-ware-for-recipes-component.html")
    public void setPreferableWareForRecipesComponent(
            long usersTableId,
            long dayMenuId,
            long eatingMenuId,
            long recipeId,
            long componentId,
            long wareId,
            HttpServletRequest request,
            PrintWriter writer) {
        UserForm user = getUserForm(request);
        Map<String, String> mp = setPreferableWareForRecipesComponentInternal(user, usersTableId, dayMenuId, eatingMenuId, recipeId, componentId, wareId);
        Jsons.serialize(mp, writer);

    }

/*
    @RequestMapping(value = "/test-use-memory.html")
    public void testUseMemory(int i, HttpServletRequest request) {
        final int BUF_SIZE = 30*1024*1024;
        request.getSession().setAttribute("test_array" + i, new byte [BUF_SIZE]);
    }
*/

    private Map<String, String> setPreferableWareForRecipesComponentInternal(
            UserForm user,
            long usersTableId,
            long dayMenuId,
            long eatingMenuId,
            long recipeId,
            long componentId,
            long wareId) {

        Map<String, String> mp = new HashMap<String, String>();
        UsersTableForm usersTable = user.getUsersTable(usersTableId);
        if (usersTable == null) {
            mp.put("result", "FAIL");
            return mp;
        }
        DayMenuForm dayMenu = usersTable.getDayMenu(dayMenuId);
        if (dayMenu == null) {
            mp.put("result", "FAIL");
            return mp;
        }
        EatingMenuForm eatingMenu = dayMenu.getEatingMenu(eatingMenuId);
        if (eatingMenu == null) {
            mp.put("result", "FAIL");
            return mp;
        }
        EatingMenuDishRecipeForm eatingMenuRecipe = eatingMenu.getEatingMenuRecipeByRecipeId(recipeId);
        if (eatingMenuRecipe == null) {
            mp.put("result", "FAIL");
            return mp;
        }

        WareForm ware = CacheManager.getInstance().getWareForm(wareId);
        if (ware == null) {
            mp.put("result", "FAIL");
            return mp;
        }

        CookingDishComponentForm component = eatingMenuRecipe.getRecipe().getComponent(componentId);
        if (component == null) {
            mp.put("result", "FAIL");
            return mp;
        }

        hiber.execute(new SetPreferableWareForRecipesComponent(user, component, ware));

        UserForm.UsersWare usersWare = user.getUsersWare(wareId);

        mp.put("result", "OK");
        mp.put("usersWarePrice", usersWare != null ? usersWare.getWareUserPriceStrValue() : "-");
        return mp;
    }
}
